package daybook.model.transaction;

import daybook.Resources;
import daybook.annotation.Bean;
import daybook.exception.ValidationException;
import daybook.model.Commodity;
import daybook.model.DC;
import org.immutables.value.Value;

import java.math.BigDecimal;
import java.math.RoundingMode;

@Bean
@Value.Immutable
public abstract class Item {
    // 买入或卖出的数量, 以account的commodity为单位
    @Value.Parameter
    public abstract BigDecimal getCount();
    // 买入或卖出的成本, 以book的defaultCurrency为单位
    @Value.Parameter
    public abstract BigDecimal getCost();

    public BigDecimal getAmount(int dc) {
        final BigDecimal amount = getAmount();
        return dc == DC.CREDIT ? amount.negate() : amount;
    }

    public BigDecimal getAmount() {
        return getCost().multiply(getCount())
                .setScale(getCost().scale(), RoundingMode.HALF_EVEN);
    }

    public BigDecimal getProduct() {
        return getCost().multiply(getCount());
    }

    public String toPrettyString() {
        return getCount().toPlainString() + " @ " + getCost().toPlainString();
    }

    // 不需要外部信息的校验
    public void validate() {
        if (getCost().signum() < 0) {
            throw ValidationException.of(Resources.ErrorMessages.NEGATIVE_COST, getCost());
        }

        if (getCount().signum() < 0) {
            throw ValidationException.of(Resources.ErrorMessages.NEGATIVE_COUNT, getCount());
        }
    }

    // 需要外部信息的校验
    public void validate(Commodity commodity, Commodity defaultCurrency) {
        validate();
        if (getCost().scale() != defaultCurrency.getFractionDigitCount()) {
            throw ValidationException.of(Resources.ErrorMessages.INVALID_COMMODITY_FRACTION,
                    getCost(), defaultCurrency.getFractionDigitCount());
        }

        if (getCount().scale() != commodity.getFractionDigitCount()) {
            throw ValidationException.of(Resources.ErrorMessages.INVALID_COMMODITY_FRACTION,
                    getCount(), commodity.getFractionDigitCount());
        }
    }
}
